package com.mla.fastdfs.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.github.pagehelper.PageInfo;
import com.github.pagehelper.util.StringUtil;
import com.mla.fastdfs.commom.RandomValidateCode;
import com.mla.fastdfs.commom.RedisConstant;
import com.mla.fastdfs.commom.Result;
import com.mla.fastdfs.dto.RoleDto;
import com.mla.fastdfs.dto.UserDto;
import com.mla.fastdfs.pojo.Permission;
import com.mla.fastdfs.pojo.User;
import com.mla.fastdfs.service.UserService;
import com.mla.fastdfs.utils.Assert;
import com.mla.fastdfs.utils.PasswordUtil;
import com.mla.fastdfs.utils.RedisUtil;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.session.Session;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.*;

/**
 * z
 *
 * @author Jun
 * @version v1.0
 * @date 2020-08-05
 */
@RestController
@RequestMapping(value = "/user")
public class UserController {

    @Autowired
    private UserService userService;
    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    private RandomValidateCode randomValidateCode;


    @RequestMapping(value = "/login", method = RequestMethod.POST)
    public Result login(String username, String password, String code, String codeKey) {
        Assert.notNull(username, "用户名不能为空");
        Assert.notNull(password, "用户密码不能为空");
        Assert.notNull(code, "验证码不能为空");

        try {
            Object object = redisUtil.hget(RedisConstant.LOGINCODE, codeKey);
            if (object == null || !code.toLowerCase().equals(object.toString().toLowerCase())) {
                return Result.error("验证码错误，请重新输入");
            }

            User user = userService.getByName(username);
            if (user == null ||
                    !user.getPassword().equals(PasswordUtil.md5Password(username, password.toUpperCase()))) {
                return Result.error("用户名或账号错误！");
            }
            if(!user.getStatus().equals(0))
                return Result.error("该账号已被锁定，请联系管理员！");

            String sessionId = shiroLogin(user);

            Map<String, Object> map = new HashMap<>();
            map.put("aToken", sessionId);
            map.put("user", user);
            redisUtil.hset(RedisConstant.LOGINUSER, sessionId, user, 60 * 60 * 24 * 7);
            return Result.ok(map);
        } catch (AuthenticationException e) {
            return Result.error("用户名或者密码错误");
        }
    }

    /**
     * 组装token，登录，将用户信息缓存到redis
     *
     * @param user
     */
    private String shiroLogin(User user) {
        // 组装token
        UsernamePasswordToken token = new UsernamePasswordToken(user.getUserName(), user.getPassword().toCharArray());
        Session session = SecurityUtils.getSubject().getSession();
        session.setAttribute(RedisConstant.SSO_USER, user);
        // shiro登陆验证
        SecurityUtils.getSubject().login(token);

        authorizationInfo(user, session.getId().toString());
        return session.getId().toString();
    }

    private void authorizationInfo(User user, String sessionId) {
        List<String> roles = new ArrayList<>();
        List<String> permissions = new ArrayList<>();
        // 添加权限 和 角色信息

        RoleDto role = userService.getByRole(user.getId());
        if (role != null) {
            if (role.getCode().equals("Admin")) {
                roles.add("*");
                permissions.add("*");
            } else {
                roles.add(role.getRoleName());
                for (Permission permission : role.getPermissions()) {
                    permissions.add(permission.getPage());
                }
            }
        }

        redisUtil.hset(RedisConstant.USERROLE, sessionId, roles, 60 * 61);
        redisUtil.hset(RedisConstant.USERPERMISSION, sessionId, permissions, 60 * 61);
    }


    @RequestMapping("/logout")
    public Result logout(String token) {
        if (StringUtil.isEmpty(token)) {
            return Result.error("缺少token");
        }
        redisUtil.hdel(RedisConstant.USERROLE, token);
        redisUtil.hdel(RedisConstant.USERPERMISSION, token);
        redisUtil.hdel(RedisConstant.LOGINUSER, token);
        return Result.ok();
    }


    @GetMapping("/code")
    public void getCode(HttpServletRequest request, HttpServletResponse response, String uuid) {
        randomValidateCode.getRandcode(request, response, uuid);
    }

    /**
     * 管理员保存
     *
     * @param request
     * @param response
     * @param record
     * @return
     */
    @RequestMapping(value = "/adminSave", method = RequestMethod.POST)
    public Result adminSave(HttpServletRequest request, HttpServletResponse response, UserDto record) {

        if (record.getId() == null) {
            record.setId(UUID.randomUUID().toString().replace("-", ""));
            User user = new User();
            user.setId(record.getId());
            user.setUserName(record.getUserName());
            if (userService.checkUserNameExist(user)) {
                return Result.error("账户已存在");
            }

            userService.adminInsert(record);
        } else {
            User user = new User();
            user.setId(record.getId());
            user.setUserName(record.getUserName());
            if (userService.checkUserNameExist(user)) {
                return Result.error("账户已存在");
            }

            userService.adminUpdate(record);
        }
        return Result.ok();
    }


    @RequestMapping(value = "/del", method = RequestMethod.POST)
    public Result del(HttpServletRequest request, HttpServletResponse response, String id) {
        if (StringUtil.isEmpty(id)) {
            return Result.error("id不能为空");
        }

        userService.removeById(id);
        return Result.ok();
    }

    @RequestMapping(value = "/selectById", method = RequestMethod.POST)
    public Result selectByPrimaryKey(HttpServletRequest request, HttpServletResponse response, String id) {
        if (StringUtil.isEmpty(id)) {
            return Result.error("id不能为空");
        }

        UserDto info = userService.selectById(id);
        return Result.ok(info);
    }

    @RequestMapping(value = "/list", method = RequestMethod.POST)
    public Result getList(HttpServletRequest request, HttpServletResponse response, User record) {
        /*条件判断*/

        List<User> list = userService.getList(record);
        return Result.ok(list);
    }

    @RequestMapping(value = "/pageList", method = RequestMethod.POST)
    public Result pageList(HttpServletRequest request, HttpServletResponse response, UserDto record,
                           @RequestParam(value = "pageNo", defaultValue = "1") Integer pageNo,
                           @RequestParam(value = "pageSize", defaultValue = "20") Integer pageSize) {
        /*条件判断*/
        PageInfo<UserDto> info = userService.pageList(record, pageNo, pageSize);
        return Result.ok(info);
    }

    @RequestMapping(value = "/editPassword", method = RequestMethod.POST)
    public Result editPassword(@RequestParam(value = "aToken") String token,
                               @RequestParam(value = "oldPassword") String oldPassword,
                               @RequestParam(value = "newPassoword") String newPassoword,
                               @RequestParam(value = "confirmPassword") String confirmPassword) {
        if (!newPassoword.equals(confirmPassword)) {
            return Result.error("确认密码错误");
        }

        if (oldPassword.equals(newPassoword)) {
            return Result.ok();
        }

        User user = (User) (redisUtil.hget(RedisConstant.LOGINUSER, token));
        if (user == null) {
            return Result.error("用户不存在或登录已过期");
        }
        if (!user.getPassword().equals(PasswordUtil.md5Password(user.getUserName(), oldPassword.toUpperCase()))) {
            return Result.error("原密码错误");
        }
        String newPassword = PasswordUtil.md5Password(user.getUserName(), newPassoword.toUpperCase());
        User user1 = new User();
        user1.setId(user.getId());
        user1.setPassword(newPassword);
        userService.updateById(user1);
        user.setPassword(newPassword);
        redisUtil.hset(RedisConstant.LOGINUSER, token, user, 60 * 60);
        return Result.ok();
    }

    @RequestMapping(value = "/editPd", method = RequestMethod.POST)
    public Result editPd(@RequestParam(value = "csId") String csId,
                         @RequestParam(value = "newPassoword") String newPassoword,
                         @RequestParam(value = "confirmPassword") String confirmPassword) {
        if (!newPassoword.equals(confirmPassword)) {
            return Result.error("确认密码错误");
        }
        UserDto dto = userService.selectById(csId);

        if (dto == null) {
            return Result.error("未找到该用户");
        }
        User user = new User();
        user.setId(dto.getId());
        user.setPassword(PasswordUtil.md5Password(dto.getUserName(),newPassoword.toUpperCase()));
        userService.updateUser(user);
        return Result.ok();
    }
}